package pl.edu.agh.jemo.quicktests;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import pl.edu.agh.jemo.evolution.algorithm.impl.SPEA2Algorithm;
import pl.edu.agh.jemo.evolution.genotype.impl.DoubleGenotype;
import pl.edu.agh.jemo.evolution.objfunc.ObjectiveFunctionSet;
import pl.edu.agh.jemo.evolution.objfunc.impl.ExtremaFinderObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.FitnessSharingObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.MichalewiczObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.PopulationCentroidObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.RastriginObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.SchweffelObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.Simple2DObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.SimpleYetMoreComplicated2DObjectiveFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.weighted.WeightedCrowdingObjectiveFunction;
import pl.edu.agh.jemo.evolution.operator.common.DomainControl;
import pl.edu.agh.jemo.evolution.operator.crossover.impl.LinearCrossover;
import pl.edu.agh.jemo.evolution.operator.crossover.impl.Radial2DCrossover;
import pl.edu.agh.jemo.evolution.operator.mutation.impl.BalancedMutation;
import pl.edu.agh.jemo.evolution.operator.mutation.impl.RadialMutation;
import pl.edu.agh.jemo.evolution.population.Population;
import pl.edu.agh.jemo.evolution.selections.impl.BinaryTournament;
import pl.edu.agh.jemo.evolution.selections.impl.ClassicTournament;
import pl.edu.agh.jemo.evolution.specimen.impl.SPEA2Specimen;
import pl.edu.agh.jemo.gui.LoggerHelper;

public class QuickSPEA2Test {

	public static void main(String[] args) {
		
		LoggerHelper.getInstance().addConsoleAppender();
		LoggerHelper.getInstance().setLevel(Level.INFO);
		Logger logger = LoggerHelper.getInstance().getLogger();
		int populationSize = 1000;
		int steps = 40;
		
		Population population = new Population();
		
		BalancedMutation balancedMutation = new BalancedMutation();
		balancedMutation.setDomainControl(DomainControl.MOVE_TO_BORDER);
		balancedMutation.setImproveSpecimen(false);
		balancedMutation.setMutationChance(0.5);
		balancedMutation.setStrongMutationChance(0.05);
//		mutation = new EmptyMutation();
		
		RadialMutation radialMutation = new RadialMutation();
		radialMutation.setDomainControl(DomainControl.MOVE_TO_BORDER);
//		radialMutation.setDomainControl(DomainControl.GENERATE_NEXT);
		radialMutation.setImproveSpecimen(true);
		radialMutation.setMutationChance(0.5);
		radialMutation.setRadius(2.);

		Radial2DCrossover radialCrossover = new Radial2DCrossover();
		radialCrossover.setCrossoverChance(0.5);
		radialCrossover.setDomainControl(DomainControl.MOVE_TO_BORDER);
//		crossover.setDomainControl(DomainControl.GENERATE_NEXT);
		radialCrossover.setImproveSpecimen(false);
//		crossover = new EmptyCrossover();
		
		LinearCrossover linearCrossover = new LinearCrossover();
		linearCrossover.setCrossoverChance(0.5);
		linearCrossover.setDomainControl(DomainControl.MOVE_TO_BORDER);
		linearCrossover.setImproveSpecimen(false);

		
		
		ClassicTournament tournament = new ClassicTournament();
		tournament.setExpectedPopulationSize(populationSize);
		tournament.setProbability(.6);
		tournament.setTournamentSizeRatio(.6);
		BinaryTournament binaryTournament = new BinaryTournament();
		binaryTournament.setExpectedPopulationSize(populationSize);
//		tournament = new EmptyTournament();
		
		
		SPEA2Algorithm algorithmByManio = new SPEA2Algorithm();
		algorithmByManio.setPopulation(population);
		algorithmByManio.setCrossover(radialCrossover);
//		algorithmByManio.setCrossover(linearCrossover);
//		algorithmByManio.setMutation(balancedMutation);
		algorithmByManio.setMutation(radialMutation);
		algorithmByManio.setSteps(steps);
//		algorithmByManio.setTournament(tournament);
		algorithmByManio.setTournament(binaryTournament);
		
		//sin(x)*(sin(((x**2)/pi)))**4 + sin(y)*(sin(((2*y**2)/pi)))**4
		
		ObjectiveFunctionSet set = new ObjectiveFunctionSet();
		
		Simple2DObjFunc simple0 = new Simple2DObjFunc();
		Simple2DObjFunc simple2 = new Simple2DObjFunc();
		simple2.setZero(2.);
		simple0.setZero(0.);
		SimpleYetMoreComplicated2DObjectiveFunc yet = new SimpleYetMoreComplicated2DObjectiveFunc();
		
		//set.add(simple0);
//		set.add(yet);
//		set.add(simple2);
		
//		SchweffelObjFunc schw = new SchweffelObjFunc();
//		set.add(schw);
		MichalewiczObjFunc michalewicz = new MichalewiczObjFunc();
		michalewicz.setM(2.);
//		set.add(michalewicz);
		SchweffelObjFunc schweffel = new SchweffelObjFunc();
//		set.add(schweffel);
		RastriginObjFunc rastrigin = new RastriginObjFunc();
		set.add(rastrigin);
		
		FitnessSharingObjectiveFunction fun = new FitnessSharingObjectiveFunction();
		fun.setNicheRadius(.2);
		PopulationCentroidObjectiveFunction popCenFun = new PopulationCentroidObjectiveFunction();
		set.add(popCenFun);
//		set.add(fun);
		WeightedCrowdingObjectiveFunction wco = new WeightedCrowdingObjectiveFunction(popCenFun, schweffel, 3d);

		
		ExtremaFinderObjectiveFunction extrema = new ExtremaFinderObjectiveFunction();
		extrema.setRadius(0.01);
		extrema.setSampleSize(300);
		
		

//		set.add(extrema);
		

		
		algorithmByManio.setObjectiveFunctionSet(set);
		algorithmByManio.setPopulationSize(populationSize);
		algorithmByManio.setSpecimenType(SPEA2Specimen.class);
		algorithmByManio.setGenotypeType(DoubleGenotype.class);
		algorithmByManio.setArchiveSize(600);
		algorithmByManio.setHillClimbingMultiplier(0.5);
	
		algorithmByManio.start();
	}
}
